package controller

import (
	"errors"
	"github.com/gin-gonic/gin"
	"shop-common/library/env"
	"shop-common/library/serializer"
	"shop-common/library/variables"
	"shop-common/utils/contextArgs"
	"shop-common/utils/pagehelper"
	"shop-common/utils/password"
	"shop-common/utils/queryWrapper"
	"shop-security/token"
	"shop-sys/business"
	"shop-sys/cache"
	"shop-sys/model"
	"shop-sys/pkg/code"
	"shop-sys/pkg/constant"
	"shop-sys/pkg/dto"
	"shop-sys/pkg/request"
)

type SysUserController struct {
}

// @Tags 用户管理
// @Summary 新增管理员
// @description: 新增管理员
// @function: Save
// @Accept  json
// @Produce  json
// @Param data body request.SysUserInsertRequest true "请求参数"
// @Success 200 {object} string "{"code":2," result":{}, "message":"注册成功", "time":1618493448}"
// @Router /sys/user [post]
func Save(ctx *gin.Context) {
	form := request.SysUserInsertRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}
	// 检查用户名
	exist, err := business.ServiceImpl().SysUserService.CheckUserExistCustom(queryWrapper.Eq("username", form.Username))

	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	} else if exist {
		serializer.Fail(ctx, code.StatusText(code.UserExist))
		return
	}

	// 检查邮箱
	exist, err = business.ServiceImpl().SysUserService.CheckUserExistCustom(queryWrapper.Eq("email", form.Email))
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	} else if exist {
		serializer.Fail(ctx, code.StatusText(code.EmailExist))
		return
	}

	// 检查手机号
	exist, err = business.ServiceImpl().SysUserService.CheckUserExistCustom(queryWrapper.Eq("mobile", form.Mobile))
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	} else if exist {
		serializer.Fail(ctx, code.StatusText(code.MobileExist))
		return
	}

	//记录注册账号管理员ID
	internalId, _ := contextArgs.GetUserInternalId(ctx)

	var internalIds []uint
	if len(form.RoleIdList) > 0 {
		internalIds, _ = business.ServiceImpl().SysRoleService.FindInRoleIds(form.RoleIdList)
	}

	err = business.ServiceImpl().SysUserService.CreateUserAndUserRole(&form, internalId, internalIds)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.InsertUserErr))
	} else {
		serializer.Success(ctx, code.StatusText(code.RegisterSuccess))
	}
}

// @Tags 用户管理
// @Summary 用户登陆
// @description: 用户登陆：登陆成功后返回code：2，accessToken、refreshExpireTime及过期时间。
// @function: Login
// @Accept  json
// @Produce  json
// @Param id path string true "captchaId"
// @Param code path int int "验证码"
// @Param data body request.SysUserLoginRequest true "请求参数"
// @Success 200 {object} string "{"code":2," result":{"accessToken": "***", accessExpireTime: 1618504505, refreshToken: "***", refreshExpireTime: 1621089305}, "message":"登陆成功", "time":1618493448}"
// @Router /sys/user/login/{captchaId}/{code} [post]
func Login(ctx *gin.Context) {
	form := request.SysUserLoginRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	tokenMap, err := business.ServiceImpl().SysUserService.Login(&form, contextArgs.GetDevice(ctx))
	if err != nil {
		serializer.Fail(ctx, err.Error())
	} else {
		serializer.SuccessData(ctx, code.StatusText(code.LoginSuccess), tokenMap)
	}
}

// @Tags 用户管理
// @Summary 刷新token
// @description: 用户登陆：登陆成功后返回code：2，accessToken、refreshExpireTime及过期时间。
// @function: RefreshToken
// @Accept  json
// @Produce  json
// @Param data body request.RefreshRequest true "请求参数"
// @Success 200 {object} string "{"code":2," result":{"accessToken": "***", accessExpireTime: 1618504505, refreshToken: "***", refreshExpireTime: 1621089305}, "message":"登陆成功", "time":1618493448}"
// @Router /sys/user/refresh [put]
func RefreshToken(ctx *gin.Context) {
	form := request.RefreshRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	oldAccessToken := form.AccessToken
	claims, err := token.ParseToken(token.JwtSecret, oldAccessToken)
	if err == token.TokenExpired {
		// 刷新token
		setNewToken(ctx, oldAccessToken)
	} else if claims == nil {
		serializer.Fail(ctx, code.StatusText(code.TokenInvalidErr))
	} else {
		serializer.Fail(ctx, code.StatusText(code.TokenNotRefresh))
	}
}

func setNewToken(ctx *gin.Context, oldAccessToken string) {
	user, err := token.GetCacheUser(oldAccessToken)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	if user == nil {
		serializer.Fail(ctx, "登陆已失效!")
		return
	}

	roles, err := business.ServiceImpl().SysUserService.ListRoleIdByUserId(user.Id)
	if err != nil {
		serializer.Fail(ctx, "刷新token")
		return
	}

	cache.SetUserOnlineRole(variables.RedisConn, user.UserId, roles)
	accessToken, err := token.RefreshAccessToken(ctx, oldAccessToken, user, contextArgs.GetDevice(ctx))
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	result := map[string]interface{}{
		"accessToken": accessToken,
	}
	if env.IsDevMode() {
		result["swaggerToken"] = "Bearer " + accessToken
	}
	serializer.SuccessData(ctx, code.StatusText(code.TokenRefreshSuccess), result)
}

// @Tags 用户管理
// @description: 分页用户列表
// @Summary 所有用户列表
// @Security ApiKeyAuth
// @function: Page
// @Accept  json
// @Produce  json
// @Param current query string false "当前页，默认1"
// @Param size query string false "每页大小，默认10"
// @Param keyword query string false "keyword"
// @Param status query string false "状态  1:停用 2:启用"
// @Success 200 {object} string "{"code":1," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/page [get]
func (u *SysUserController) Page(ctx *gin.Context) {
	form := pagehelper.SearchPageRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	user, err := business.ServiceImpl().SysUserService.PageUser(&form)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	}
	serializer.SuccessData(ctx, "", user)
}

// @Tags 用户管理
// @Summary 获取登录的用户信息
// @description: 获取登录的用户信息
// @Security ApiKeyAuth
// @function: Info
// @Accept  json
// @Produce  json
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/info [get]
func (u *SysUserController) Info(ctx *gin.Context) {
	shopId, err := contextArgs.GetSHopId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	internalId, err := contextArgs.GetUserInternalId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	sysUser, roleIds, err := privateGetUser(ctx, shopId, queryWrapper.Eq("id", internalId))
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	serializer.SuccessData(ctx, "", &dto.SysUserDTO{
		UserId:     sysUser.UserId,
		Username:   sysUser.Username,
		Email:      sysUser.Email,
		Mobile:     sysUser.Mobile,
		Status:     sysUser.Status,
		RoleIdList: roleIds,
	})
}

// @Tags 用户管理
// @Summary 用户信息
// @description: 用户信息
// @Security ApiKeyAuth
// @function: GetByUid
// @Accept  json
// @Produce  json
// @Param uid path string true "uuid"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/info/{userId} [get]
func (u *SysUserController) GetByUid(ctx *gin.Context) {
	shopId, err := contextArgs.GetSHopId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	userId, err := contextArgs.GetUriPath(ctx, "userId")
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	sysUser, rids, err := privateGetUser(ctx, shopId, queryWrapper.Eq("user_id", userId))

	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	serializer.SuccessData(ctx, "", map[string]interface{}{
		"userId":     sysUser.UserId,
		"username":   sysUser.Username,
		"email":      sysUser.Email,
		"mobile":     sysUser.Mobile,
		"status":     sysUser.Status,
		"roleIdList": rids,
	})
}

func privateGetUser(ctx *gin.Context, shopId uint, pair *queryWrapper.WherePair) (*model.SysUser, []uint, error) {
	sysUser, err := business.ServiceImpl().SysUserService.FindOne(pair)
	if err != nil {
		return nil, nil, errors.New(code.StatusText(code.ERROR))
	}

	if sysUser == nil || shopId != sysUser.ShopId {
		return nil, nil, errors.New(code.StatusText(code.UserInfoNotPermission))
	}

	//获取用户所属的角色列表
	roleIds, err := business.ServiceImpl().SysUserService.ListRoleIdByUserId(sysUser.Id)
	if err != nil {
		return nil, nil, errors.New(code.StatusText(code.ERROR))
	}

	if len(roleIds) > 0 {
		fileterIds, _ := business.ServiceImpl().SysRoleService.FindInRoleIds(roleIds)
		return sysUser, fileterIds, nil
	}

	return sysUser, nil, nil
}

// @Tags 用户管理
// @Summary 修改用户
// @description: 修改用户
// @Security ApiKeyAuth
// @function: Update
// @Accept  json
// @Produce  json
// @Param data body request.SysUserUpdateRequest true "请求参数"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user [put]
func (u *SysUserController) Update(ctx *gin.Context) {
	form := request.SysUserUpdateRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	if form.UserId == "" {
		serializer.Fail(ctx, code.StatusText(code.InvalidParams))
		return
	}

	shopId, err := contextArgs.GetSHopId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	sysUser, err := business.ServiceImpl().SysUserService.FindOne(queryWrapper.Eq("user_id", form.UserId))
	if err != nil {
		serializer.Fail(ctx, serializer.PublicUpdateErr)
		return
	}

	if sysUser == nil || shopId != sysUser.ShopId {
		serializer.Fail(ctx, code.StatusText(code.UserInfoNotPermission))
		return
	}

	if sysUser.Id == constant.SUPER_ADMIN_ID && form.Status != 2 {
		serializer.Fail(ctx, "系统管理员不能停用")
		return
	}

	// 检查用户名
	if form.Username != sysUser.Username {
		serializer.Fail(ctx, code.StatusText(code.UserNotExist))
		return
	}

	var roleIds []uint
	if len(form.RoleIdList) > 0 {
		roleIds, _ = business.ServiceImpl().SysRoleService.FindInRoleIds(form.RoleIdList)
	}

	//err = business.ServiceImpl().SysUserService.UpdateUserAndUserRole(ctx, &form, sysUser.Id, roleIds)
	//if err != nil {
	//	serializer.Fail(ctx, code.StatusText(code.UpdateErr))
	//	return
	//}

	// 更新redis改用户存放的角色信息
	serializer.Success(ctx, code.StatusText(code.UpdateSuccess))
	_ = business.ServiceImpl().SysUserService.UpdateCacheUserRoles(sysUser.UserId, roleIds)
}

// @Tags 用户管理
// @Summary 修改用户状态
// @description: 修改用户状态
// @Security ApiKeyAuth
// @function: UpdateStatus
// @Accept  json
// @Produce  json
// @Param data body request.UpdateSysUserStatusRequest true "请求参数"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/status [put]
func (u *SysUserController) UpdateStatus(ctx *gin.Context) {
	form := request.UpdateSysUserStatusRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	sysUser, err := business.ServiceImpl().SysUserService.FindOne(queryWrapper.Eq("user_id", form.UserId))

	if err != nil {
		serializer.Fail(ctx, serializer.PublicUpdateErr)
		return
	}

	if sysUser != nil && sysUser.Id == 1 && form.Status == constant.SYS_USER_DISABLE {
		serializer.Fail(ctx, "系统管理员不能禁用")
		return
	}

	//if form.UserId <= 0 {
	//	serializer.Fail(ctx, code.StatusText(code.InvalidParams))
	//	return
	//}

	//if form.UserId == 1 && form.Status == constant.SYS_USER_DISABLE {
	//	serializer.Fail(ctx, "系统管理员不能禁用")
	//	return
	//}

	shopId, err := contextArgs.GetSHopId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	//sysUser, err := business.ServiceImpl().SysUserService.GetSysUserById(ctx, form.UserId)
	//if err != nil {
	//	serializer.Fail(ctx, code.StatusText(code.ERROR))
	//	return
	//}

	if sysUser == nil || shopId != sysUser.ShopId {
		serializer.Fail(ctx, code.StatusText(code.UserInfoNotPermission))
		return
	}

	// 检查request.status跟repository一致，直接返回。
	if form.Status == sysUser.Status {
		serializer.Success(ctx, code.StatusText(code.UpdateSuccess))
		return
	}

	if sysUser.Id == constant.SUPER_ADMIN_ID && form.Status == constant.SYS_USER_DISABLE {
		serializer.Fail(ctx, "系统管理员不能禁用")
		return
	}

	user := model.SysUser{
		Id:     sysUser.Id,
		Status: form.Status,
	}

	err = business.ServiceImpl().SysUserService.UpdateUserStatus(&user)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.UpdateErr))
		return
	}

	serializer.Success(ctx, code.StatusText(code.UpdateSuccess))
}

// @Tags 用户管理
// @Summary 修改密码
// @description: 修改当前登陆用户的密码
// @Security ApiKeyAuth
// @function: Password
// @Accept  json
// @Produce  json
// @Param data body request.PasswordRequest true "请求参数"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/password [put]
func (u *SysUserController) Password(ctx *gin.Context) {
	form := request.PasswordRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	userId, err := contextArgs.GetUserInternalId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	sysUser, err := business.ServiceImpl().SysUserService.FindById(userId)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicUpdateErr)
		return
	}

	// 检查原密码是否正确
	isPass := password.Check(sysUser.Password, sysUser.PasswordSalt, form.Password)
	if !isPass {
		serializer.Fail(ctx, code.StatusText(code.PasswordNotPass))
		return
	}

	err = business.ServiceImpl().SysUserService.UpdatePasswordByUserId(userId, form.NewPassword)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.UpdateErr))
		return
	}

	auth, err := contextArgs.GetAuth(ctx)
	if err == nil {
		go func() {
			token.Destroy(ctx, auth)
		}()
	}
	serializer.Success(ctx, code.StatusText(code.UpdateSuccess))
}

// @Tags 用户管理
// @Summary 删除用户
// @description: 删除用户
// @Security ApiKeyAuth
// @function: Delete
// @Accept  json
// @Produce  json
// @Param uid path string true "uuid"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/user/{userId} [delete]
func (u *SysUserController) Delete(ctx *gin.Context) {
	currentUserId, err := contextArgs.GetUserInternalId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	// 判断是不是超级用户,这里要去获取userId == 1 或者roles里有超级管理员
	if currentUserId != constant.SUPER_ADMIN_ID {
		serializer.Fail(ctx, "当前用户不能进行删除操作!")
		return
	}

	userId, err := contextArgs.GetUriPath(ctx, "userId")
	if err != nil {
		serializer.Fail(ctx, "请选择需要删除的用户")
		return
	}

	sysUser, err := business.ServiceImpl().SysUserService.FindOne(queryWrapper.Eq("user_id", userId))

	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.ERROR))
		return
	}

	if sysUser == nil {
		serializer.Fail(ctx, "未找到该用户!")
		return
	}

	if sysUser.Id == constant.SUPER_ADMIN_ID {
		serializer.Fail(ctx, "系统管理员不能删除!")
		return
	}

	pair := &queryWrapper.WherePair{Query: "user_id = ?", Args: []interface{}{sysUser.UserId}}
	pair = pair.And(&queryWrapper.WherePair{Query: "shop_id = ?", Args: []interface{}{sysUser.ShopId}})

	err = business.ServiceImpl().SysUserService.Delete(sysUser.Id)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicDeleteErr)
		return
	}

	serializer.Success(ctx, "")
}

// @Tags 用户管理
// @Summary 退出登陆
// @description: 删除用户
// @Security ApiKeyAuth
// @function: Logout
// @Accept  json
// @Produce  json
// @Router /sys/user/logout [delete]
func (u *SysUserController) Logout(ctx *gin.Context) {
	auth, err := contextArgs.GetAuth(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	err = token.Destroy(ctx, auth)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.ERROR))
		return
	}

	serializer.Success(ctx, "")
}
